package com.sprucetec.live.controller;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.fastjson.JSON;
import com.sprucetec.live.annotation.SystemControllerLog;
import com.sprucetec.live.base.entity.User;
import com.sprucetec.live.common.dto.PagedListDTO;
import com.sprucetec.live.common.dto.business.LiveUserDto;
import com.sprucetec.live.common.dto.business.LiveVideoDto;
import com.sprucetec.live.common.dto.business.NettyMessageDto;
import com.sprucetec.live.common.util.*;
import com.sprucetec.live.common.webcontext.LoginUserContext;
import com.sprucetec.live.entity.LiveUser;
import com.sprucetec.live.entity.LiveVideo;
import com.sprucetec.live.entity.LiveVideoData;
import com.sprucetec.live.enums.LiveStatusEnum;
import com.sprucetec.live.service.LiveVideoDataService;
import com.sprucetec.live.service.LiveVideoService;
import com.sprucetec.live.service.RedisService;
import com.sprucetec.live.util.SsoUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.WebAsyncTask;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Callable;

/**
 * @ClassName LiveVideoController
 * @Description:
 * @Author Kenny
 * @Date 2020/3/31
 **/

@Slf4j
@RestController
@RequestMapping("/liveVideo")
public class LiveVideoController {


    @Autowired
    private LiveVideoService liveVideoService;

    @Autowired
    private LiveVideoDataService liveVideoDataService;


    @Autowired
    private RedisService redisService;

    /**
     * 分页查询直播列表
     *
     * @param liveVideoDto
     * @return
     */
    @PostMapping("getLiveVidePage")
    public ServiceResult<PagedListDTO<LiveVideoDto>> getLiveVidePage(@RequestBody LiveVideoDto liveVideoDto) {
        liveVideoDto.judgePage();
        return ServiceResultUtil.success(liveVideoService.getLiveVidePage(liveVideoDto));
    }

    /**
     * 直播设置功能
     */
    @SystemControllerLog(description = "视频设置")
    @PostMapping("setVideo")
    public ServiceResult setVideo(@RequestBody LiveVideoDto liveVideoDto) throws Exception {
        LiveVideoDto liveVideo = liveVideoService.setVideo(liveVideoDto);
        return ServiceResultUtil.success(liveVideo);
    }

    /**
     * 创建直播
     *
     * @param liveVideoDto
     * @return
     */
    @PostMapping("createLiveVideo")
    @SystemControllerLog(description = "创建直播")
    public ServiceResult<String> createLiveVideo(@RequestBody LiveVideoDto liveVideoDto) {
        liveVideoService.createLiveVideo(liveVideoDto);
        return ServiceResultUtil.success("创建成功");
    }

    /**
     * 修改直播
     *
     * @param liveVideoDto
     * @return
     */
    @SystemControllerLog(description = "修改直播")
    @PostMapping("updateLiveVideo")
    public ServiceResult<String> updateLiveVideo(@RequestBody LiveVideoDto liveVideoDto) {
        liveVideoService.updateLiveVideo(liveVideoDto);
        return ServiceResultUtil.success("修改成功");
    }

    /**
     * 根据id，获取直播详情
     *
     * @param id
     * @return
     */
    @GetMapping(value = "getLiveVideoDto")
    public ServiceResult<LiveVideoDto> getLiveVideoDto(@RequestParam(value = "id") Long id) {
        if (id == null) {
            return ServiceResultUtil.fail(RespCode.ERROR, "参数错误：id不能为空");
        }
        return ServiceResultUtil.success(liveVideoService.getLiveVideoDto(id));
    }

    /**
     * 获取统计数据
     *
     * @param liveVideo
     * @return
     */
    @PostMapping(value = "getLiveVideoData")
    public ServiceResult<LiveVideoData> getLiveVideoData(@RequestBody LiveVideo liveVideo) {
        if (StringUtils.isBlank(liveVideo.getLiveNo())) {
            return ServiceResultUtil.fail(RespCode.ERROR, "参数错误：直播编码不能为空");
        }
        return ServiceResultUtil.success(liveVideoDataService.getLiveVideoData(liveVideo));
    }

    /**
     * 导出在线人数
     *
     * @param response
     * @param obj
     * @return
     */
    @RequestMapping(value = "exportOnlineUser", produces = "application/json; charset=utf-8")
    public ServiceResult<String> exportOnlineUser(HttpServletResponse response, String obj) {
        LiveVideo liveVideo = new LiveVideo();
        if (StringUtils.isNotEmpty(obj)) {
            liveVideo = JSON.parseObject(obj, LiveVideo.class);
        }

        String fileName = liveVideo.getTitle() + "_在线人_" + DateFormatUtils.formatDate(new Date(), "yyyyMMdd");
        try (ServletOutputStream out = response.getOutputStream()) {
            ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
            // 设置SHEET名称
            Sheet sheet = new Sheet(1, 0);
            sheet.setSheetName("sheet1");
            String[] headerArr = new String[]{"观看人", "观看人工号", "IP", "进入时间"};
            // 设置标题
            Table table = new Table(1);
            List<List<String>> titles = new ArrayList<>();
            for (String header : headerArr) {
                titles.add(Collections.singletonList(header));
            }
            table.setHead(titles);
            // 查数据写EXCEL
            List<List<String>> dataList = new ArrayList<>();
            List<LiveUserDto> liveUsers = liveVideoService.getOnlineUserByLiveNo(liveVideo);
            if (!CollectionUtils.isEmpty(liveUsers)) {
                liveUsers.stream().filter(x -> StringUtils.isNotBlank(x.getUserName())).forEach(liveUser -> dataList.add(Arrays.asList(
                        liveUser.getUserName(),
                        liveUser.getUserCode(),
                        liveUser.getUserLoginIp(),
                        DateFormatUtils.toStr("yyyy-MM-dd hh:mm:ss", liveUser.getCreateTime())
                        )
                ));
            }
            log.info("数据准备完成=====" + LocalDateTime.now().toString());
            writer.write0(dataList, sheet, table);
            // 下载EXCEL
            response.setHeader("Content-disposition", "attachment;filename=" + new String(fileName.getBytes("GBK"), "ISO8859_1") + ".xlsx");
            response.setContentType("multipart/form-data");
            response.setCharacterEncoding("utf-8");
            writer.finish();
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
            log.info(fileName, e);
            return ServiceResultUtil.fail(RespCode.ERROR, "IO异常");
        }
        log.info("导出文件完成=====" + LocalDateTime.now().toString());
        return ServiceResultUtil.success(fileName + "导出成功");
    }

    /**
     * 清空聊天服务器 Channel 缓存
     */
    @RequestMapping("clearChannel")
    public ServiceResult<Integer> clearChannel(@RequestBody NettyMessageDto nettyMessageDto) {
        if (StringUtils.isBlank(nettyMessageDto.getLiveNo())) {
            return ServiceResultUtil.fail(RespCode.ERROR, "参数错误ID不能为空");
        }
        return ServiceResultUtil.success(liveVideoService.clearChannel(nettyMessageDto));
    }
    /************************************************************ PC 端相关接口 START ************************************************************/

    /**
     * 直播详情 1.数据统计: 在线人数 峰值人数 观看次数 统计 2.直播详情相关数据加载（聊天、留言）
     *
     * @param liveVideoDto 视频Dto
     */
    @PostMapping("getVideoDetail")
    public WebAsyncTask<ServiceResult> getVideoDetail(@RequestBody LiveVideoDto liveVideoDto, HttpServletRequest request) {
        User loginUser = SsoUtil.getLoginUser();
        log.info("获取到得登录人ip" + loginUser.getIp());
        Callable<ServiceResult> callable = new Callable() {
            @Override
            public Object call() {
                ServiceResult serviceResult = new ServiceResult();
                LiveVideoDto videoDetail = liveVideoService.getVideoDetail(liveVideoDto.getLiveNo(), liveVideoDto.getIp(), liveVideoDto.getCity());

                serviceResult.setBody(videoDetail);
                //更新redis相关数据统计信息(异步)
                if (videoDetail.getLiveStatus().equals(LiveStatusEnum.LIVEING.getCode())) { // 只有正在直播的才统计直播数据
                    liveVideoDto.setVideoId(videoDetail.getId().toString());
                    try {
                        liveVideoDto.setUsername(loginUser.getName());
                        liveVideoDto.setUid(loginUser.getUid());
                        liveVideoDto.setIp(loginUser.getIp());
                        liveVideoService.videoDetailData(liveVideoDto);
                    } catch (Exception ex) {
                        log.error("查看视频详情，数据统计失败，视频LiveNo=>{}, error=>{}", liveVideoDto.getLiveNo(), ex.toString());
                    }
                }
                serviceResult.setMessage("加载详情成功");
                serviceResult.setSuccess(true);
                return serviceResult;
            }
        };
        return new WebAsyncTask<>(callable);
    }


    @PostMapping("getOtherVideoOfDetailPage")
    public WebAsyncTask<ServiceResult> getOtherVideoOfDetailPage(@RequestBody LiveVideoDto liveVideoDto) {
        Callable<ServiceResult> callable = new Callable() {
            @Override
            public Object call() {
                ServiceResult serviceResult = new ServiceResult();
                serviceResult.setBody(liveVideoService.getNewLastedVideos(liveVideoDto.getIsDetail()));
                serviceResult.setMessage("加载详情页其它视频成功");
                serviceResult.setSuccess(true);
                return serviceResult;
            }
        };
        return new WebAsyncTask(callable);
    }

    /**
     * 监听界面离开, 修改在线观看人数
     */
    @PostMapping("userAway")
    public ServiceResult userAway(@RequestBody LiveVideoDto liveVideoDto) {
        User loginUser = SsoUtil.getLoginUser();
        loginUser.setName(loginUser.getName());
        loginUser.setIp(loginUser.getIp());
        redisService.videoDetailAway(liveVideoDto);
        return ServiceResultUtil.success(null);
    }

    /**
     * 获取PC端首页数据
     *
     * @param liveUser 当前用户
     * @return
     */
    @PostMapping(value = "getIndexVideo")
    public WebAsyncTask<ServiceResult> getIndexVideo(@RequestBody LiveUser liveUser) {
        Callable<ServiceResult> callable = new Callable() {
            @Override
            public Object call() throws Exception {
                ServiceResult serviceResult = new ServiceResult();
                serviceResult.setBody(liveVideoService.getIndexVideo(liveUser));
                serviceResult.setMessage("加载主页数据完成");
                serviceResult.setSuccess(true);
                log.info("获取到执行结果，当前线程为" + Thread.currentThread().getName());
                return serviceResult;
            }
        };
        return new WebAsyncTask<>(callable);
    }

    @PostMapping(value = "videoSearch")
    public WebAsyncTask<ServiceResult> videoSearch(@RequestBody LiveVideoDto liveUserDto) {
        Callable<ServiceResult> callable = new Callable() {
            @Override
            public Object call() throws Exception {
                ServiceResult serviceResult = new ServiceResult();
                serviceResult.setBody(liveVideoService.videoSearch(liveUserDto));
                serviceResult.setMessage("视频搜索完成");
                serviceResult.setSuccess(true);
                return serviceResult;
            }
        };
        return new WebAsyncTask<>(callable);
    }

    /************************************************************ PC 端相关接口 END ************************************************************/


    @GetMapping("getPrivateIp")
    public ServiceResult getPrivateIp(HttpServletRequest request) {
        return ServiceResultUtil.success(LoginUserContext.getUser().getIp());
    }

}
